/*!
    \copyright  Copyright (c) 2020 - 2025 Qualcomm Technologies International, Ltd.
                All Rights Reserved.
                Qualcomm Technologies International, Ltd. Confidential and Proprietary.
    \file
    \addtogroup le_bap
    \brief
    @{
*/

#ifndef PACS_UTILITIES_H_
#define PACS_UTILITIES_H_

#include "gatt_pacs_server.h"
#ifdef USE_SYNERGY
#include "bap_server_prim.h"
#else
#include "bap_server.h"
#endif
#include "bt_types.h"
#include "pacs_config.h"

#define PACS_PREFERRED_AUDIO_CONTEXTS_TYPE  0x1

/*! \brief Structure storing PACS record handle list. */
typedef struct
{
    uint8   handle_count;
    uint16  handles[1];
} le_bap_pacs_records_t;

/*! \brief Initialises the Published Audio Capabilities Service (PACS),

     Creates the PACS server instance, note this must be called before GATT Initialisation is completed
 */
void LeBapPacsUtilities_Init(void);

/*! \brief Allows the addition of a single sink/source PAC record.

    \param sink_or_source[in]   Indicates if the record to add is a sink or source PAC.
    \param additional_pac[in]   Pointer to the PAC record to add. Format of PAC record need to be specified as BapServerPacsRecord
                                for standard PAC record format and BapServerVSPacsRecord for VS PAC record format.
    \param vendor_specific[in]  TURE if PAC record to add is in VS PAC record format.
                                FALSE if PAC record to add is in standard PAC record format.
 */
void LeBapPacsUtilities_AddPacRecord(PacsServerDirectionType sink_or_source, const void * additional_pac, bool vendor_specific);

/*! \brief Gets PACS record (list of handles) for sink or source PACS.

    \param[in] for_sink TRUE indicates for source, else for sink PACS.

    \return PACS record pointer (Shouldn't freed or altered or stored)
 */
const le_bap_pacs_records_t* LeBapPacsUtilities_GetPacHandles(bool for_sink);

/*! \brief Gets the Sink audio locations as currently set in PACS

    \return The current sink audio loactions
 */
uint32 LeBapPacsUtilities_GetSinkAudioLocations(void);

/*! \brief Gets the Source audio locations as currently set in PACS

    \return The current source audio locations
 */
uint32 LeBapPacsUtilities_GetSourceAudioLocations(void);

/*! \brief Sets the Sink Audio Locations in PACS

    \param audio_locations
 */
void LeBapPacsUtilities_SetSinkAudioLocations(uint32 audio_locations);

/*! \brief Sets the Source Audio Locations in PACS

    \param audio_locations
 */
void LeBapPacsUtilities_SetSourceAudioLocations(uint32 audio_locations);

/*! \brief Sets the supported Sink audio contexts in PACS

    \param audio_contexts
 */
void LeBapPacsUtilities_SetSinkSupportedAudioContexts(uint16 audio_contexts);

/*! \brief Sets the supported source audio contexts in PACS

    \param audio_contexts
 */
void LeBapPacsUtilities_SetSourceSupportedAudioContexts(uint16 audio_contexts);

/*! \brief Gets the Sink audio context availability as currently set in PACS

    \return The current audio context availability
 */
uint16 LeBapPacsUtilities_GetSinkAudioContextAvailability(void);

/*! \brief Sets the Sink audio context availability in PACS

    \param audio_contexts
 */
void LeBapPacsUtilities_SetSinkAudioContextAvailability(uint16 audio_contexts);

/*! \brief Gets the Source audio context availability as currently set in PACS

    \return The current audio context availability
 */
uint16 LeBapPacsUtilities_GetSourceAudioContextAvailability(void);

/*! \brief Sets the Source audio context availability in PACS

    \param audio_contexts
 */
void LeBapPacsUtilities_SetSourceAudioContextAvailability(uint16 audio_contexts);

/*! \brief Checks if the specified Sink audio context is available in PACS

    \param audio_contexts
 */
bool LeBapPacsUtilities_IsSinkAudioContextAvailable(PacsAudioContextType audio_context);

/*! \brief Utility function to check if a given codec ID and codec specific configuration is supported according to the current PACS records

    \param coding_format
    \param company_id
    \param vendor_specific_codec_id
    \param sampling_frequency
    \param frame_duration
    \param octets_per_frame

    \returns TRUE if a matching PAC record is found, else FALSE
 */
bool LeBapPacsUtilities_IsCodecIdAndSpecificCapabilitiesSupportedBySink(uint8 coding_format, 
                                                                        uint16 company_id, 
                                                                        uint16 vendor_specific_codec_id,
                                                                        PacsSamplingFrequencyType sampling_frequency,
                                                                        PacsFrameDurationType frame_duration,
                                                                        uint16 octets_per_frame);

/*! \brief Gets the Source audio context availability as currently set in PACS

    \return The current audio context availability
 */
uint16 LeBapPacsUtilities_GetSourceAudioContextAvailability(void);

/*! \brief Sets the Source audio context availability in PACS

    \param audio_contexts
 */
void LeBapPacsUtililties_SetSourceAudioContextAvailability(uint16 audio_contexts);

/*! \brief Checks if the specified Source audio context is available in PACS

    \param audio_contexts
 */
bool LeBapPacsUtilities_IsSourceAudioContextAvailable(PacsAudioContextType audio_context);

/*! \brief Utility function to check if a given codec config is supported according to the current PACS records

    \param coding_format
    \param company_id
    \param vendor_specific_codec_id

    \returns TRUE if a matching PAC record is found, else FALSE
 */
bool LeBapPacsUtilities_IsCodecConfigSupportedBySource(uint8 coding_format, uint16 company_id, uint16 vendor_specific_codec_id);

/*! \brief Set the Bap handle as PAC instance handle 
    \param bap_handle   BAP profile handle 
*/
void LeBapPacsSetBapHandle(ServiceHandle bap_handle);

/*! \brief Get the Bap handle as PAC instance handle

    \return bap_handle   BAP profile handle 
*/
ServiceHandle LeBapPacsGetBapHandle(void);

/*! \brief Check LC3 EPC license.
 
    \return Returns TRUE if license is available
 */
bool LeBapPacsUtilities_Lc3EpcLicenseCheck(void);

/*! \brief Get the LC3 frame length in the SDU
 
    \return Returns LC3 frame length
 */
uint16 LeBapPacsUtilities_Lc3GetFrameLength(uint16 max_sdu_size, uint16 blocks_per_sdu, uint16 audio_channel_mask);

/*! \brief Get PACS record of the Source/Sink

    \param is_source TRUE if PACS to be retrieved is from Source else FALSE
    \param pacs_count

    \return Returns PACS record of the Source/Sink
 */
const GattPacsServerRecordType* LeBapPacsUtilities_GetPacs(bool is_source, uint16 *pacs_count);

/*! \brief Converts sampling frequency to PACS sampling frequency type

    \param sampling_frequency sampling frequency to be converted

    \return Returns PACS sampling frequency
 */
PacsSamplingFrequencyType LeBapPacsUtilities_GetPacsSamplingFreqBitMaskFromFreq(uint32 sampling_frequency);

/*! \brief Gets the preferred Audio context from the PACS record

    \param pac_metadata metadata from PACS record
    \param pac_metadata_len length of metadata

    \return Returns Preferred Audio context from PACS recrd
 */

AudioContextType LeBapPacsUtilities_GetPreferredAudioContext(const uint8 *pac_metadata , uint8 pac_metadata_len);

/*! \brief Retrieve Client config
    \param cid Connection id 

    \return Returns the retrieved client config
 */
void * LeBapPacsUtilities_RetrieveClientConfig(gatt_cid_t cid);

/*! \brief Store Client config
    \param cid Connection id 
    \param config The config data to be stored
    \param size Size of config data
 */
void LeBapPacsUtilities_StoreClientConfig(gatt_cid_t cid, void * config, uint8 size);

/*! \brief This API is used to validate Streaming Audio context from PACS available Audio context
           (Non Selective audio context and Selective Both).
    \param cid             GATT connection id of the LE audio source
    \param is_sink         Is direction sink/source
    \param context_in_use  context already under use/claimed
    \param metadata        Pointer to LTV data.
    \param metadataLength  Length of metadata

    \return TRUE if success, FALSE otherwise
 */
bool LeBapPacsUtilities_ValidateStreamingContext(unsigned cid, bool is_sink, uint16 context_in_use, uint8 *metadata, uint8 *metadataLength);

#if (defined (INCLUDE_LE_APTX_ADAPTIVE) || defined (INCLUDE_LE_AUDIO_GAMING_MODE_APTX_LITE)) && defined (USE_SYNERGY)

/*! \brief Get PACS record of the Source/Sink (where the PACs record is of VS type)

    \param is_source TRUE if PACS to be retrieved is from Source else FALSE
    \param pacs_count

    \return Returns VS PACS record of the Source/Sink
 */

const GattPacsServerVSPacRecord* LeBapPacsUtilities_GetPacsVS(bool is_source, uint16 *pacs_count, uint8 vs_codec);

/*! \brief Gets the preferred Audio context from the VS PACS record

    \param pac_record PACS record from which audio context to be fetched

    \return Returns Preferred Audio context from VS PACS recrd
 */

PacsSamplingFrequencyType LeBapPacsUtilities_GetSampleRateFromVSPac(const GattPacsServerVSPacRecord *pacs_record);

#endif /* INCLUDE_LE_APTX_ADAPTIVE */

/*! \brief Check if PACS is connected or not using cid

    \param cid GATT Connection id for which connection to be checked.

    \return TRUE if PACS is connected
 */
bool LeBapPacsUtilities_IsPacsConnected(gatt_cid_t cid);
#endif /* PACS_UTILITIES_H_ */
/*! @} */